package logger

import (
	"fmt"
	log "github.com/sirupsen/logrus"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"sync"
)

var prop = make(map[string]interface{})
var isInit bool
var lock = sync.Mutex{}
var fileName = "logger.yaml"

func LoadConf(file string) {
	fmt.Printf("ready to load logger config...")

	lock.Lock()
	defer lock.Unlock()

	if isInit {
		fmt.Printf("logger has been init. ignored currently ..")
		return
	}

	if file == "" {
		file = fileName
	} else {
		fileName = file
	}

	data, err := ioutil.ReadFile(file)
	if err != nil {
		log.Panicf("failed to load logger configuration file with error: %v\n", err)
	}

	err = yaml.Unmarshal(data, &prop)
	if err != nil {
		log.Panic("failed to unmarshal logger config items - ", data, err)
	}

	replaceEnvConfig()

	log.Printf("loaded logger config items - %v", &prop)

	loadConfigLog()

	isInit = true
}

func SetConfigFile(file string) {
	if file == "" {
		return
	}

	fileName = file
}

func replaceEnvConfig()  {
	env := getEnv()
	if env == "" {
		env = "prod"
	}

	if env == "prod" {
		log.Println("prod env. do nothing")
		return
	}

	log.Printf("ready to replace %v config \n", env)

	envConf, ok := prop[env]
	if !ok {
		return
	}

	for k, v := range envConf.(map[interface{}]interface{}) {
		prop[k.(string)] = v
	}
}

func getEnv() string {
	env := os.Getenv("env")
	if env == "" {
		env = "prod"
	}
	return env
}

func GetString(key string, defaultValue string) string {
	return get(key, defaultValue).(string)
}

func GetInt(key string, defaultValue int) int {
	value := get(key, defaultValue)
	switch value.(type) {
	case string:
		value, _ = strconv.Atoi(value.(string))
		return value.(int)
	default:
		return value.(int)
	}
}

func get(key string, defaultValue interface{}) interface{} {
	keys := strings.Split(key, ".")

	var value interface{} = prop

	for _, v := range keys {
		if value == nil {
			return defaultValue
		}

		switch value.(type) {
		case map[interface{}]interface{}:
			value = value.(map[interface{}]interface{})[v]
		case map[string]interface{}:
			value = value.(map[string]interface{})[v]
		default:
			return value
		}
	}

	if value == nil {
		return defaultValue
	}

	return value
}